package com.ydzt.fanka.server.space.consumer;

import java.sql.Connection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import org.apache.log4j.Logger;

import com.ydzt.fanka.server.domain.BufferRecord;
import com.ydzt.fanka.server.domain.CommunicationNode;
import com.ydzt.fanka.server.domain.ParamDefine;
import com.ydzt.fanka.server.domain.ReturnInfo;
import com.ydzt.fanka.server.indb.Indb;
import com.ydzt.fanka.server.init.InitData;
import com.ydzt.fanka.server.log.LoggerFanka;
import com.ydzt.fanka.server.persistence.BufferStore;
import com.ydzt.fanka.server.space.bufferreceiver.BufferReceiverPool;
import com.ydzt.fanka.server.utils.ByteConvert;
import com.ydzt.fanka.server.utils.DBHelper;
import com.ydzt.fanka.server.utils.FileUtil;

//将队列中的报文解包入库 并进行具体的处理
public class SocketConsumer extends Thread {
	static Logger logger = Logger.getLogger(SocketConsumer.class.getName());
	List<BufferRecord> broadcastPkgList = null;
	// List<Element> broadcastList = null;
	List<CommunicationNode> broadcastList = null;
	String bufferID = null;
	String strSender = null;
	byte[] msgMgrType = null;
	byte[] pkg = null;
	byte[] rev = null;
	byte[] sender = null;
	byte[] stmtdayByte;
	private HashMap<String, ParamDefine> paramDefine;
	private Connection conn;

	public SocketConsumer(HashMap<String, ParamDefine> paramDefine,
			Connection conn) {
		this.paramDefine = paramDefine;
		this.conn = conn;
	}

	private boolean createPackageToBroadcast(
			List<CommunicationNode> broadcastList) {
		try {
			if (broadcastList != null) {
				for (Iterator<CommunicationNode> it = broadcastList.iterator(); it
						.hasNext();) {
					BufferRecord bufferTmp = new BufferRecord();
					byte[] pkgTmp = this.pkg;
					CommunicationNode elm = (CommunicationNode) it.next();
					String recevier = elm.getNodeIP();
					int port = elm.getNodePort();
					byte[] recevierIP = ByteConvert
							.ipv4Address2BinaryArray(recevier);
					if (port > 32767) {
						port = port - 65536;
					}
					byte[] recevierPort = ByteConvert
							.shortToBytes((short) port);
					System.arraycopy(recevierIP, 0, pkgTmp, 6, 4);
					System.arraycopy(recevierPort, 0, pkgTmp, 10, 2);
					bufferTmp.setBufferContent(pkgTmp);
					bufferTmp.setBufferId(UUID.randomUUID().toString());
					if (0 != BufferStore.writePackageIntoBroadcast(bufferTmp)) {
						logger.error("将" + bufferTmp.getBufferId()
								+ "写进broadcast文件夹失败");
						return false;
					}
				}
			}
			return true;
		} catch (Exception e) {
			logger.error("生成广播报文失败!" + e.getMessage());
			return false;
		}
	}

	@Override
	public void run() {
		logger.info("初始化解包入库线程-> " + Thread.currentThread().getName()
				+ " 成功...");

		while (true) {
			synchronized (this) {

				BufferRecord bufferRecord = null;
				bufferRecord = BufferReceiverPool.getInstants()
						.getBufferReceiver();
				if (bufferRecord == null) {
					try {
						Thread.sleep(100);
						continue;
					} catch (InterruptedException e) {
						continue;
					}
				} else {
					pkg = bufferRecord.getBufferContent();
					msgMgrType = new byte[1];
					try {
						// 读取包处理类型
						System.arraycopy(pkg, 12, msgMgrType, 0, 1);
					} catch (Exception e) {
						logger.error("错误的包");
						logger.error(LoggerFanka.dumpBin(pkg));
					}

					bufferID = bufferRecord.getBufferId();
					if (pkg != null && bufferID != null) {
						// 将buffer中读出的包 解析入库
						ReturnInfo returnInfo = Indb.decodeInsertDB(pkg,
								paramDefine, conn);
						if (returnInfo.isSuccess()) {
							// 入库成功则写入备份
							if (BufferStore
									.writePackageIntoBackup(bufferRecord)) {

								if (!InitData.nodeType.equals("00")) {// 食堂计算机
									if (msgMgrType[0] == 0x02) {// 表示
																// 此包是由POS发送给食堂的
																// 要存进transmit文件夹
																// 等待transmit线程处理
										if (BufferStore
												.writePackageIntoTransmit(bufferRecord)) {
											if (!FileUtil
													.deleteOnlyReadFile(bufferRecord)) {// 此包已经解析入库
																						// 并且已经备份
																						// 也已经被放入transmit文件夹等待发送至中心
																						// 则在onlyread中删除
												logger.error("在onlyread文件夹中删除包"
														+ bufferRecord
																.getBufferId()
														+ "失败");// 记录下删除失败的包的名称
																// 此包与备份中的包重复
											} else {
											}
										} else {
											logger.error("将包"
													+ bufferRecord
															.getBufferId()
													+ "写进transmit文件夹失败");
										}
									}
									if (msgMgrType[0] == 0x00) {// 表示
																// 此消息来自中心
																// 并且需要下发给POS
																// 这些消息将被存进broadcast文件夹
										// 获取广播列表 并对包头中的接收方字段进行赋值
										logger.info("食堂收到00类型报文,此消息来自中心并且需要下发给POS");
										logger.info("正在获取类型为POS的通信节点信息...");
										// broadcastList =
										// XmlUtil.GetOneRecordDefine(InitData.pos_list);
										broadcastList = DBHelper
												.getCommunicationNodeByType("POS");
										logger.info("取得以下通信节点");
										for (int i = 0; i < broadcastList
												.size(); i++) {
											CommunicationNode commNode = broadcastList
													.get(i);
											logger.info(commNode.getNodeID()
													+ "/"
													+ commNode.getNodeName()
													+ "/"
													+ commNode.getNodeIP()
													+ "/"
													+ commNode.getNodePort());
										}
										if (this.createPackageToBroadcast(broadcastList)) {
											if (!FileUtil
													.deleteOnlyReadFile(bufferRecord)) {
												logger.error("在onlyread文件夹中删除包"
														+ bufferRecord
																.getBufferId()
														+ "失败");
											} else {
											}
										}
									}
									if (msgMgrType[0] == 0x01) {// 表示次报文来自中心
																// 并且要求不发给POS
																// 比如通知日终
										if (!FileUtil
												.deleteOnlyReadFile(bufferRecord)) {
											logger.error("在onlyread文件夹中删除包"
													+ bufferRecord
															.getBufferId()
													+ "失败");
										} else {
										}
									}
								} else if (InitData.nodeType.equals("00")) {
									// 解析报文发送节点
									this.sender = new byte[4];
									System.arraycopy(this.pkg, 2, this.sender,
											0, 4);
									strSender = ByteConvert
											.bcd2Str(this.sender);
									if (msgMgrType[0] == 0x00) {// 表示
																// 此消息是来自应用管理的广播
																// 并且需要下发给各个食堂
																// 这些消息将被存进broadcast文件夹
										logger.info("中心接收到处理类型为00的报文");
										// 获取广播列表 并对包头中的接收方字段进行赋值
										broadcastList = DBHelper
												.getCommunicationNodeByType("DR");
										logger.info("取得以下通信节点");
										for (int i = 0; i < broadcastList
												.size(); i++) {
											CommunicationNode commNode = broadcastList
													.get(i);
											logger.info(commNode.getNodeID()
													+ "/"
													+ commNode.getNodeName()
													+ "/"
													+ commNode.getNodeIP()
													+ "/"
													+ commNode.getNodePort());
										}
										if (this.createPackageToBroadcast(broadcastList)) {
											if (!FileUtil.deleteOnlyReadFile(
													bufferRecord, strSender)) {
												logger.error("在onlyread文件夹中删除包"
														+ bufferRecord
																.getBufferId()
														+ "失败");
											} else {
											}
										}
									} else if (msgMgrType[0] == 0x03
											|| msgMgrType[0] == 0x01) {// 表示此包来自食堂
										logger.info("中心接收到处理类型为03的报文");
										if (!FileUtil.deleteOnlyReadFile(
												bufferRecord, strSender)) {
											logger.info("节点参数:" + strSender);
											logger.error("在onlyread文件夹中删除包"
													+ bufferRecord
															.getBufferId()
													+ "失败");
										} else {
										}
									}
								}
							} else {
								logger.error("将" + bufferRecord.getBufferId()
										+ "写入buffer文件夹失败");
							}
							try {
								Thread.sleep(20);
							} catch (InterruptedException e) {
								e.printStackTrace();
								continue;
							}
						} else {
							BufferStore.writePackageIntoErrorFile(bufferRecord,
									returnInfo.getErrorType());
							logger.error("对报文文件" + bufferRecord.getBufferId()
									+ "解析入库失败 已被放入error_pkg文件夹");
							// 20130626 入库失败的文件被存进error_pkg文件夹 并在onlyread中删除
							if (FileUtil.deleteOnlyReadFile(bufferRecord)) {
								logger.info("错误文件" + bufferRecord.getBufferId()
										+ "已经在onlyread中删除");
							} else {
								logger.error("错误文件"
										+ bufferRecord.getBufferId()
										+ "未在onlyread中删除");
								logger.error("尝试重新删除"
										+ bufferRecord.getBufferId() + "文件");
								while (!FileUtil
										.deleteOnlyReadFile(bufferRecord)) {
									logger.error("尝试重新删除"
											+ bufferRecord.getBufferId() + "文件");
									try {
										Thread.sleep(1000);
									} catch (InterruptedException e) {
									}
								}
							}
							try {
								Thread.sleep(20);
							} catch (InterruptedException e) {
								continue;
							}
						}
					}
				}

			}// syn结束
		}
	}
}